#include "StdAfx.h"
#include "CarManager.h"
#include "graphics/GrVector.h"
#include "GameManager.h"
#include "Car.h"
#include "Helicopter.h"

CCarManager::CCarManager(void)
{
	setBounds(0, 0, 20, 20);
	_spawnDuration = 0.1;
	_timePassed = 0;
	_carsAllowed = 10;
	_savingDistance = 1.5;
}

CCarManager::CCarManager(CGameManager *god)
{
	_gameManager = god;
}

CCarManager::~CCarManager(void)
{
	_cars.clear();
}

void CCarManager::Render()
{
	for (std::vector<CCar*>::iterator cp = _cars.begin(); cp != _cars.end(); cp++)
		(*cp)->Render();
}

void CCarManager::Update(double dt)
{
	removeCars();

	_timePassed += dt;
	if (_timePassed > _spawnDuration)
	{
		GenerateCar();
		_timePassed = 0;
	}

	for (std::vector<CCar*>::iterator cp = _cars.begin(); cp != _cars.end(); cp++)
		(*cp)->Update(dt);
}

//generate a car with a path within the bounds
void CCarManager::GenerateCar()
{
	if (_cars.size() >= (unsigned int)_carsAllowed)
		return;

	CBezierCurve bc;
	double v = double(rand()) / double(RAND_MAX) * 0.1 + 0.1;
	v /= 2; //half the speed
	
	//pick some walls to start and end on
	int swall = rand() % 4;
	int ewall = swall;
	while (ewall == swall)
		ewall = rand() % 4;
	double x, z;

	x = double(rand())/double(RAND_MAX) * _bounds.Z() + _bounds.X();
	z = double(rand())/double(RAND_MAX) * _bounds.W() + _bounds.Y();

	switch(swall)
	{
	case 0: //left wall (x-axis)
		if (x < 4.5) x = 4.5;
		bc.setControlPoint(0, CGrVector(x, 0, 0));
		break;
	case 1: //bottom wall (z-axis)
		if (z < 4.5) z = 4.5;
		bc.setControlPoint(0, CGrVector(0, 0, z));
		break;
	case 2: //right wall
		bc.setControlPoint(0, CGrVector(x, 0, _bounds.W()));
		break;
	case 3: //top wall
		bc.setControlPoint(0, CGrVector(_bounds.Z(), 0, z));
		break;
	}
	
	x = double(rand())/double(RAND_MAX) * _bounds.Z() + _bounds.X();
	z = double(rand())/double(RAND_MAX) * _bounds.W() + _bounds.Y();
	
	switch(ewall)
	{
	case 0: //left wall (x-axis)
		if (x < 4.5) x = 4.5;
		bc.setControlPoint(3, CGrVector(x, 0, 0));
		break;
	case 1: //bottom wall (z-axis)
		if (z < 4.5) z = 4.5;
		bc.setControlPoint(3, CGrVector(0, 0, z));
		break;
	case 2: //right wall
		bc.setControlPoint(3, CGrVector(x, 0, _bounds.W()));
		break;
	case 3: //top wall
		bc.setControlPoint(3, CGrVector(_bounds.Z(), 0, z));
		break;
	}

	bc.setControlPoint(1, CGrVector(double(rand())/double(RAND_MAX) * (_bounds.Z() - _bounds.X()) + _bounds.X(),
			0, 
			double(rand())/double(RAND_MAX) * (_bounds.W() - _bounds.Y()) + _bounds.Y()));
	bc.setControlPoint(2, CGrVector(double(rand())/double(RAND_MAX) * (_bounds.Z() - _bounds.X()) + _bounds.X(),
			0, 
			double(rand())/double(RAND_MAX) * (_bounds.W() - _bounds.Y()) + _bounds.Y()));

	GenerateCar(bc, v);
}

void CCarManager::GenerateCar(CBezierCurve bc, double v)
{
	CCar* car = new CCar();
	car->setBezierCurve(bc);
	car->setVelocity(v);
	car->setManager(this);
	car->ID(NextGameObjectID++);
	car->setHostageCount((rand() % MAX_HOSTAGES) + 1);
	_cars.push_back(car);
}


void CCarManager::checkCarCollisionWithPlayer(CHelicopter *heli)
{
	CGrVector heliPos=heli->getPosition();
	double bound1=heliPos.X();
	double bound2=heliPos.X()+4.0;
	double bound3=heliPos.Z()+2.0;
	double bound4=heliPos.Z()+1.0; 

	double height=heliPos.Y();

	//check if heli is at height to pick up
	if (height<=_savingDistance)
	{
		double leftBound, rightBound, upBound, downBound;

		if (bound1>bound2){leftBound=bound2; rightBound=bound1;}
		else {leftBound=bound1; rightBound=bound2;}

		if (bound3>bound4){upBound=bound3; downBound=bound4;}
		else {upBound=bound4; downBound=bound3;}

		for (int i=0; i<_cars.size(); i++)
		{
			CGrVector carPos=_cars[i]->getPosition();
			if (carPos.X()>leftBound&&carPos.X()<rightBound && carPos.Z()<upBound && carPos.Z()>downBound)
			{
				int hostages=_cars[i]->getHostageCount();
				heli->addSavedHostages(hostages);
				_cars[i]->setHostageCount(0);	
			}
		
		}
	}
}

CCar* CCarManager::getCar(unsigned int ID)
{
	for (std::vector<CCar*>::iterator cp = _cars.begin(); cp != _cars.end(); cp++)
		if ((*cp)->ID() == ID)
			return (*cp);
	return 0;
}

void CCarManager::removeCar(unsigned int ID)
{
	bool found = false;
	//make sure it exists
	for (std::vector<CCar*>::iterator cp = _cars.begin(); cp != _cars.end(); cp++)
		if ((*cp)->ID() == ID)
		{
			found = true;
			break;
		}

	if (found)
	{
		_toRemove.push_back(ID);
	}
}

void CCarManager::removeCars()
{
	if (_toRemove.size() == 0)
		return; //nothing to take out

	//as a temporary sol'n i'm just going to remove once car a frame
	//we'll work on a better way once more pertinent tasks are dealt with
	while (_toRemove.size() > 0)
	{
		eraseCar((*_toRemove.begin()));
		_toRemove.erase(_toRemove.begin());
	}
	_toRemove.clear();
}

void CCarManager::eraseCar(unsigned int id)
{
	std::vector<CCar*>::iterator torem = _cars.end();
	//make sure it exists
	for (std::vector<CCar*>::iterator cp = _cars.begin(); cp != _cars.end(); cp++)
		if ((*cp)->ID() == id)
		{
			torem = cp;
			break;
		}

	_cars.erase(torem);
}

void CCarManager::setBounds(double l, double b, double r, double t)
{
	setBounds(CGrVector(l, b, r, t));
}
